import { createConnection, createServer, ListenOptions, Server, Socket, TcpSocketConnectOpts } from "net";
import { exit } from "process";
import ClientController from "../clientcontroller/ClientController";
import TiggerTcpServer from "../server/server";
import Tunnel from "../tunnel/tunnel";
import PacketMixer from "../packethandler/PacketMixer";
import Channel from "../channel/channel";
import { control_log } from "../log/logger";

interface client {
    referPort: number,
    connectedPort: number,
    client: Socket,
}
interface outbounds {
    [index: string]: client;
}
export default class DispatchOutbound
{
    //private outboundController: ClientController;
    private outbounds: outbounds[];

    private options: TcpSocketConnectOpts;  //目标服务器信息

    private server: TiggerTcpServer;    //控制通道（服务器）

    private channel: Channel;

    private channel_overflow_queue: Socket[];

    private counter: number;

    constructor(options: TcpSocketConnectOpts, server: TiggerTcpServer, loptions: ListenOptions)
    {
        this.options = options;
        this.server = server;
        //this.outboundController = new ClientController();
        this.outbounds = new Array<outbounds>();
        this.channel_overflow_queue = new Array<Socket>();
        this.counter = 0;

        this.server.registerControlCommand("client_port_close", (args: number[]) => {
            //客户端关闭连接, args[0] : 客户端被断开的远端端口, args[1] : 绑定至本服务器的本地外传端口
            let client:client = this.outbounds[args[0].toString()];
            if(client != undefined)
                client.client.destroy();
            this.outbounds[args[0].toString()] = undefined;
        }).registerControlCommand("client_port_open", (args: number[]) => {
            //客户端的监听器传入连接, args[0] : 客户端传入端口, 注意：现在只支持单ip传入不同端口机制
            let client = createConnection(options, () => {
                //服务器已经连接到目标服务器，向客户端回传正确连接
                this.server.pushControlDataToClient(0, "server_port_open", [args[0], client.localPort]);
                //参数0: 客户端传入端口


                //趁现在绑定客户端传入端口与本机外传端口
                let c:client = {
                    referPort: args[0],
                    connectedPort: client.localPort,
                    client: client
                };
                //this.outboundController.addClient(c);
                if(!this.channel.isChannelDrain())
                    c.client.pause();
                this.outbounds[c.referPort.toString()] = c;
            }).on("data", (data: Buffer) => {
                //console.log(++this.counter, data);
                //if(!this.channel.sendData(data, arg))
                //{
                    //console.log("多通道数据包输送时出现问题");
                //}
                if(!this.channel.sendData(data, args[0]))
                {
                    return;
                    if(!this.channel.isChannelDrain())
                    {
                        for(let i in this.outbounds)
                        {
                            let client:any = this.outbounds[i];
                            if(client != undefined)
                            {
                                client.client.pause();
                            }
                        }
                    }
                }
            }).on("close", (had_error: boolean) => {
                //control_log("目标服务器断开连接");
                this.server.pushControlDataToClient(0, "server_port_close", [args[0], client.localPort]);
            }).on("drain", () => {
                console.log("服务器>>>目标服务器缓冲空闲，channel继续");
                this.channel.resume();
            }).on("error", (err: Error) => {});

        }).registerControlCommand("tunnel_open", (args: number[]) => {
            console.log("接收到通道开通请求, 参数:" + args[0]);
            
            //通过控制通道向客户端发送通道已建立信息
            this.server.pushControlDataToClient(0, "tunnel_ok", [loptions.port]);

            this.channel = new Channel(args[0], false, true, loptions);
            this.channel.regChannelDrain(() => {

                // for(let i in this.outbounds)
                // {
                //     let client:any = this.outbounds[i];
                //     if(client != undefined)
                //     {
                //         client.client.resume();
                //     }
                // }
            }).regDataRecive((refPort: number, data: Buffer) => {
                if(this.outbounds[refPort.toString()] != undefined)
                {
                    if(!this.outbounds[refPort.toString()].client.write(data))
                    {
                        //在无法写入目标时应该暂停
                        console.log("写出问题");
                        this.channel.pause();
                    }

                }
            }).regChannelAllConnected(() => {
                console.log('所有通道已连接');
            });
        }).handleControlListen((client_id:number) => {});
    }
}